source("utilities.R")
source("variables.R")
require(ggplot2)
require(plotly)
require(cowplot)
require(splitstackshape)
require(ggpubr)
source("Table_2_rh_exploration.R")

df <- prepare_sensor_data(sensor_delay_corrected, cdt)
dt <- prepare_dusttrak_data(dusttrak_file, cdt)

df %>%
  select(sensor, exp, source, date, PM25) %>%
  filter(sensor!="SHT35") %>%
  filter(exp!="") %>%
  group_by(exp, source, sensor) %>%
  nest() -> tmp

tmp %>%
  dplyr::mutate(regression = map(data, ~clean_regression(df =.x,dusttrak = dt, 0))) %>%
  unnest(regression, .drop=TRUE)  ->res



df2<-cSplit(indt=res,splitCols = c("sensor"),sep="-",direction="wide",drop=FALSE)
df2 %>%
  select(-sensor_2,-sensor_3)->res

res <- res %>%
  flag_site_data(sensor_list)

res_rh_temp <- inner_join(res, summary_rh_temp, by = c("exp"))


#write.csv(select(res_rh_temp,-data), "C:/GitHub/AQ_analysis_lab/lm_no_enclosure_cdt_corr.csv")

res_rh_temp <- res_rh_temp %>%
  mutate(rh_median  = round2(rh_median,0))
df %>% inner_join(select(res_rh_temp, sensor, exp, source, slope, intercept, slope_p_value), by = c("sensor", "exp", "source")) -> df_coeff

df_coeff %>% 
  mutate(PM25_corr = ifelse(slope_p_value<=0.05,(PM25-intercept)/slope), -999) %>%
  filter(PM25_corr != -999) -> df_calibrated
require(trelliscopejs)
Loading required package: trelliscopejs
package 㤼㸱trelliscopejs㤼㸲 was built under R version 3.5.3
df_calibrated %>%
ggplot(aes(x = date, y = PM25_corr)) + geom_line() + facet_trelliscope(exp~sensor,ncol=5)
using data from the first layer
Using `as.character()` on a quosure is deprecated as of rlang 0.3.0.
Please use `as_label()` or `as_name()` instead.
This warning is displayed once per session.`cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)``cols` is now required.
Please use `cols = c(data)`
dusttrak <- prepare_dusttrak_data(dusttrak_file, cdt_corrected)
Error in nrow(cdt) : object 'cdt_corrected' not found

What does it looks like?

p_opcr1 <- ggplot()+
  geom_line(data = filter(df_calibrated, sensor_1=="OPCR1", exp != ""),
            aes(x = date, y = PM25_corr, group = sensor, colour = sensor, 
                text = paste0("Box: ", site,
                              "<br>Exp: ", exp,
                              "<br>Source: ", source))) +
  labs(y = "PM2.5 (ug/m3)") +
  geom_line(data = filter(dusttrak, exp != ""), aes(x = date,y = pm2.5), colour = "red", linetype = "dashed")+
  scale_x_datetime() + theme_bw() + ggtitle("OPCR1") + theme(plot.title = element_text(hjust = 0.5))+facet_wrap(~exp, ncol = 1, scales = "free_x")
Ignoring unknown aesthetics: text
p_pms5003 <- ggplot()+
  geom_line(data = filter(df_calibrated, sensor_1=="PMS5003", exp != ""),
            aes(x = date, y = PM25_corr, group = sensor, colour = sensor, 
                text = paste0("Box: ", site,
                              "<br>Exp: ", exp,
                              "<br>Source: ", source))) +
  labs(y = "PM2.5 (ug/m3)") +
  geom_line(data = filter(dusttrak, exp != ""), aes(x = date,y = pm2.5), colour = "red", linetype = "dashed")+
  scale_x_datetime() + theme_bw() + ggtitle("PMS5003") + theme(plot.title = element_text(hjust = 0.5))+facet_wrap(~exp, ncol = 1, scales = "free_x")
Ignoring unknown aesthetics: text
p_sds018 <- ggplot()+
  geom_line(data = filter(df_calibrated, sensor_1=="SDS018", exp != ""),
            aes(x = date, y = PM25_corr, group = sensor, colour = sensor, 
                text = paste0("Box: ", site,
                              "<br>Exp: ", exp,
                              "<br>Source: ", source))) +
  labs(y = "PM2.5 (ug/m3)") +
  geom_line(data = filter(dusttrak, exp != ""), aes(x = date,y = pm2.5), colour = "red", linetype = "dashed")+
  scale_x_datetime() + theme_bw() + ggtitle("SDS018") + theme(plot.title = element_text(hjust = 0.5))+facet_wrap(~exp, ncol = 1, scales = "free_x")
Ignoring unknown aesthetics: text
p_sps030 <- ggplot()+
  geom_line(data = filter(df_calibrated, sensor_1=="SPS030", exp != ""),
            aes(x = date, y = PM25_corr, group = sensor, colour = sensor, 
                text = paste0("Box: ", site,
                              "<br>Exp: ", exp,
                              "<br>Source: ", source))) +
  labs(y = "PM2.5 (ug/m3)") +
  geom_line(data = filter(dusttrak, exp != ""), aes(x = date,y = pm2.5), colour = "red", linetype = "dashed")+
  scale_x_datetime() + theme_bw() + ggtitle("SPS030") + theme(plot.title = element_text(hjust = 0.5))+facet_wrap(~exp, ncol = 1, scales = "free_x")
Ignoring unknown aesthetics: text
p_hpma <- ggplot()+
  geom_line(data = filter(df_calibrated, sensor_1=="HPMA115S0", exp != ""),
            aes(x = date, y = PM25_corr, group = sensor, colour = sensor, 
                text = paste0("Box: ", site,
                              "<br>Exp: ", exp,
                              "<br>Source: ", source))) +
  labs(y = "PM2.5 (ug/m3)") +
  geom_line(data = filter(dusttrak, exp != ""), aes(x = date,y = pm2.5), colour = "red", linetype = "dashed")+
  scale_x_datetime() + theme_bw() + ggtitle("HPMA115S0") + theme(plot.title = element_text(hjust = 0.5))+facet_wrap(~exp, ncol = 1, scales = "free_x")
Ignoring unknown aesthetics: text
ggplotly(p_opcr1, dynamicTicks = TRUE)

ggplotly(p_pms5003, dynamicTicks = TRUE)

ggplotly(p_sds018, dynamicTicks = TRUE)

ggplotly(p_sps030, dynamicTicks = TRUE)

ggplotly(p_hpma, dynamicTicks = TRUE)

Now if we extract the peaks


res_bind<-res_bind %>%
  mutate(ratio = max_value/Concentration)

require(splitstackshape)

df2<-cSplit(indt=res_bind,splitCols = c("sensor"),sep="-",direction="wide",drop=FALSE)

df2 %>%
  select(-sensor_2,-sensor_3)->res_bin

Influence of the concentration on the value of the ratio


res_bin %>%
  filter(Variation == "Peak") %>%
  ggplot(aes(x=Experiment,y=ratio)) + 
  geom_violin(draw_quantiles = c(0.25, 0.5, 0.75))+
  #geom_jitter(height= 0, width = 0,1)+
#  stat_boxplot(geom ='errorbar', width = 0.6) +
  #geom_boxplot()+
#  stat_summary(fun.data = n_fun, geom = "text", hjust = 0.5) +
  facet_wrap(sensor_1~Source,ncol=4)+ylab("Ratio sensor/dusttrak")+theme_bw()->p
p
#+scale_y_continuous(limits = quantile(res_bin$ratio, c(0.1, 0.9)))
#ggsave(p,filename = "peaks_ratio_free_axis.png",width = 12, height = 12)

res_bin %>%
  filter(Variation == "Peak") %>%
  ggplot(aes(x=Experiment,y=ratio)) + 
#  stat_boxplot(geom ='errorbar', width = 0.6) +
  geom_boxplot()+
#  stat_summary(fun.data = n_fun, geom = "text", hjust = 0.5) +
  facet_wrap(sensor_1~Source,ncol=2)+ylab("Ratio sensor/dusttrak")+theme_bw()->p
#+scale_y_continuous(limits = quantile(res_bin$ratio, c(0.1, 0.9)))
ggsave(p,filename = "peaks_ratio.png",width = 12, height = 12)


res_bin %>%
  filter(Variation == "Peak") %>%
  ggplot(aes(x=Experiment,y=ratio)) + 
#  stat_boxplot(geom ='errorbar', width = 0.6) +
  geom_boxplot(outlier.shape = NA)+
#  stat_summary(fun.data = n_fun, geom = "text", hjust = 0.5) +
  facet_wrap(sensor_1~Source,ncol=2)+ylab("Ratio sensor/dusttrak")+theme_bw()+
  scale_y_continuous(limits = c(0,quantile(res_bin$ratio, c(0.9)))) -> p
ggsave(p,filename = "peaks_ratio_no_outliers.png",width = 12, height = 12)


p<-res_bin %>%
  filter(Variation == "Peak") %>%
  ungroup() %>%
  ggplot() + geom_point(aes(x=Concentration,y=ratio,color=sensor))+facet_wrap(sensor_1~Source,ncol=4,scales="free")+ylab("Ratio sensor/dusttrak")
ggplotly(p, dynamicTicks = TRUE)

NA

Compare with uncalibrated data


res <- df %>%
    filter(date>=as.POSIXct(paste("2019-09-05", peaks[1,]$Start),tz="UTC"), date<=as.POSIXct(paste("2019-09-05", peaks[1,]$End),tz="UTC")) %>%
    group_by(sensor) %>%
  filter(PM25>=1) %>%
  summarise(max_value = max(PM25)) %>%
    mutate(Experiment = peaks[1,]$Experiment, Source = peaks[1,]$Source, Variation= peaks[1,]$Variation, Number = peaks[1,]$Number)
for(row in 2:nrow(peaks)){
  df %>%
    filter(date>=as.POSIXct(paste("2019-09-05", peaks[row,]$Start),tz="UTC"), date<=as.POSIXct(paste("2019-09-05", peaks[row,]$End),tz="UTC")) %>%
    group_by(sensor) %>%
      filter(PM25>=1) %>%
  summarise(max_value = max(PM25)) %>%
    mutate(Experiment = peaks[row,]$Experiment, Source = peaks[row,]$Source, Variation= peaks[row,]$Variation, Number = peaks[row,]$Number) -> tmp
  res<-rbind(res,tmp)
  
} 
res %>%
  inner_join(peaks, by=c("Source", "Experiment", "Variation", "Number"))  %>%
  mutate(ratio = max_value/Concentration)->res_bind_uncalibrated


res_bind$status <- "Calibrated"
res_bind_uncalibrated$status <- "Not Calibrated"
res_comparison <- rbind(res_bind, res_bind_uncalibrated)

df2<-cSplit(indt=res_comparison,splitCols = c("sensor"),sep="-",direction="wide",drop=FALSE)

df2 %>%
  select(-sensor_2,-sensor_3)->res_comparison

res_comparison$sensor_1 <- factor(res_comparison$sensor_1, levels = c("PMS5003", "SPS030", "HPMA115S0", "SDS018", "OPCR1"))

res_comparison$status <- factor(res_comparison$status, levels = c("Not Calibrated", "Calibrated"))
res_comparison %>%
  filter(Variation == "Peak") %>%
  ggplot(aes(x=Experiment,y=ratio,fill=status)) + 
   geom_boxplot(width=0.8,position=position_dodge(width = 0.8),alpha=0.8,lwd=0.3,fatten=0.8,outlier.size = 0.8,outlier.alpha=0.5,outlier.stroke=0)+
  facet_wrap(sensor_1~Source,ncol=4)+ylab("Ratio sensor/dusttrak")+theme_bw()+
  scale_y_continuous(breaks=pretty(c(-1,6), n=14),sec.axis = dup_axis(name=NULL))+
  theme(axis.text.x = element_text(angle=90,size = 6))->p
p_legend<-get_legend(p)

plot_grid(p_legend)


p<-p+theme(legend.position = "none")
p+  theme(panel.spacing = unit(0, "lines")) +
  theme(plot.margin = unit(c(0,0,0,0), "lines"))

ggsave(p,filename = "ratio_comparison_spacing.svg",unit = "mm", width= 180, height = 240)
ggsave(as_ggplot(p_legend),filename = "ratio_comparison_legend.svg",unit = "mm", width= 180, height = 240)

NA
NA
LS0tDQp0aXRsZTogIkNhbGlicmF0aW9uIG9mIHRoZSBzZW5zb3JzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7ciBzZXR1cH0NCg0Kc291cmNlKCJ1dGlsaXRpZXMuUiIpDQpzb3VyY2UoInZhcmlhYmxlcy5SIikNCnJlcXVpcmUoZ2dwbG90MikNCnJlcXVpcmUocGxvdGx5KQ0KcmVxdWlyZShjb3dwbG90KQ0KcmVxdWlyZShzcGxpdHN0YWNrc2hhcGUpDQpyZXF1aXJlKGdncHVicikNCnNvdXJjZSgiVGFibGVfMl9yaF9leHBsb3JhdGlvbi5SIikNCg0KDQpgYGANCg0KDQpgYGB7cn0NCg0KZGYgPC0gcHJlcGFyZV9zZW5zb3JfZGF0YShzZW5zb3JfZGVsYXlfY29ycmVjdGVkLCBjZHQpDQpkdCA8LSBwcmVwYXJlX2R1c3R0cmFrX2RhdGEoZHVzdHRyYWtfZmlsZSwgY2R0KQ0KDQpkZiAlPiUNCiAgc2VsZWN0KHNlbnNvciwgZXhwLCBzb3VyY2UsIGRhdGUsIFBNMjUpICU+JQ0KICBmaWx0ZXIoc2Vuc29yIT0iU0hUMzUiKSAlPiUNCiAgZmlsdGVyKGV4cCE9IiIpICU+JQ0KICBncm91cF9ieShleHAsIHNvdXJjZSwgc2Vuc29yKSAlPiUNCiAgbmVzdCgpIC0+IHRtcA0KDQp0bXAgJT4lDQogIGRwbHlyOjptdXRhdGUocmVncmVzc2lvbiA9IG1hcChkYXRhLCB+Y2xlYW5fcmVncmVzc2lvbihkZiA9LngsZHVzdHRyYWsgPSBkdCwgMCkpKSAlPiUNCiAgdW5uZXN0KHJlZ3Jlc3Npb24sIC5kcm9wPVRSVUUpICAtPnJlcw0KDQoNCg0KZGYyPC1jU3BsaXQoaW5kdD1yZXMsc3BsaXRDb2xzID0gYygic2Vuc29yIiksc2VwPSItIixkaXJlY3Rpb249IndpZGUiLGRyb3A9RkFMU0UpDQpkZjIgJT4lDQogIHNlbGVjdCgtc2Vuc29yXzIsLXNlbnNvcl8zKS0+cmVzDQoNCnJlcyA8LSByZXMgJT4lDQogIGZsYWdfc2l0ZV9kYXRhKHNlbnNvcl9saXN0KQ0KDQpyZXNfcmhfdGVtcCA8LSBpbm5lcl9qb2luKHJlcywgc3VtbWFyeV9yaF90ZW1wLCBieSA9IGMoImV4cCIpKQ0KDQoNCiN3cml0ZS5jc3Yoc2VsZWN0KHJlc19yaF90ZW1wLC1kYXRhKSwgIkM6L0dpdEh1Yi9BUV9hbmFseXNpc19sYWIvbG1fbm9fZW5jbG9zdXJlX2NkdF9jb3JyLmNzdiIpDQoNCnJlc19yaF90ZW1wIDwtIHJlc19yaF90ZW1wICU+JQ0KICBtdXRhdGUocmhfbWVkaWFuICA9IHJvdW5kMihyaF9tZWRpYW4sMCkpDQpgYGANCg0KDQpgYGB7cn0NCmRmICU+JSBpbm5lcl9qb2luKHNlbGVjdChyZXNfcmhfdGVtcCwgc2Vuc29yLCBleHAsIHNvdXJjZSwgc2xvcGUsIGludGVyY2VwdCwgc2xvcGVfcF92YWx1ZSksIGJ5ID0gYygic2Vuc29yIiwgImV4cCIsICJzb3VyY2UiKSkgLT4gZGZfY29lZmYNCg0KZGZfY29lZmYgJT4lIA0KICBtdXRhdGUoUE0yNV9jb3JyID0gaWZlbHNlKHNsb3BlX3BfdmFsdWU8PTAuMDUsKFBNMjUtaW50ZXJjZXB0KS9zbG9wZSksIC05OTkpICU+JQ0KICBmaWx0ZXIoUE0yNV9jb3JyICE9IC05OTkpIC0+IGRmX2NhbGlicmF0ZWQNCg0KZGYyPC1jU3BsaXQoaW5kdD1kZl9jYWxpYnJhdGVkLHNwbGl0Q29scyA9IGMoInNlbnNvciIpLHNlcD0iLSIsZGlyZWN0aW9uPSJ3aWRlIixkcm9wPUZBTFNFKQ0KDQpkZjIgJT4lDQogIHNlbGVjdCgtc2Vuc29yXzIsLXNlbnNvcl8zKS0+ZGZfY2FsaWJyYXRlZA0KYGBgDQoNCldoYXQgZG9lcyBpdCBsb29rcyBsaWtlPw0KDQpgYGB7cn0NCnBfb3BjcjEgPC0gZ2dwbG90KCkrDQogIGdlb21fbGluZShkYXRhID0gZmlsdGVyKGRmX2NhbGlicmF0ZWQsIHNlbnNvcl8xPT0iT1BDUjEiLCBleHAgIT0gIiIpLA0KICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gUE0yNV9jb3JyLCBncm91cCA9IHNlbnNvciwgY29sb3VyID0gc2Vuc29yLCANCiAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUwKCJCb3g6ICIsIHNpdGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkV4cDogIiwgZXhwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5Tb3VyY2U6ICIsIHNvdXJjZSkpKSArDQogIGxhYnMoeSA9ICJQTTIuNSAodWcvbTMpIikgKw0KICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihkdCwgZXhwICE9ICIiKSwgYWVzKHggPSBkYXRlLHkgPSBwbTIuNSksIGNvbG91ciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSsNCiAgc2NhbGVfeF9kYXRldGltZSgpICsgdGhlbWVfYncoKSArIGdndGl0bGUoIk9QQ1IxIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkrZmFjZXRfd3JhcCh+ZXhwLCBuY29sID0gMSwgc2NhbGVzID0gImZyZWVfeCIpDQoNCg0KcF9wbXM1MDAzIDwtIGdncGxvdCgpKw0KICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihkZl9jYWxpYnJhdGVkLCBzZW5zb3JfMT09IlBNUzUwMDMiLCBleHAgIT0gIiIpLA0KICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gUE0yNV9jb3JyLCBncm91cCA9IHNlbnNvciwgY29sb3VyID0gc2Vuc29yLCANCiAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUwKCJCb3g6ICIsIHNpdGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkV4cDogIiwgZXhwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5Tb3VyY2U6ICIsIHNvdXJjZSkpKSArDQogIGxhYnMoeSA9ICJQTTIuNSAodWcvbTMpIikgKw0KICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihkdCwgZXhwICE9ICIiKSwgYWVzKHggPSBkYXRlLHkgPSBwbTIuNSksIGNvbG91ciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSsNCiAgc2NhbGVfeF9kYXRldGltZSgpICsgdGhlbWVfYncoKSArIGdndGl0bGUoIlBNUzUwMDMiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKStmYWNldF93cmFwKH5leHAsIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikNCg0KcF9zZHMwMTggPC0gZ2dwbG90KCkrDQogIGdlb21fbGluZShkYXRhID0gZmlsdGVyKGRmX2NhbGlicmF0ZWQsIHNlbnNvcl8xPT0iU0RTMDE4IiwgZXhwICE9ICIiKSwNCiAgICAgICAgICAgIGFlcyh4ID0gZGF0ZSwgeSA9IFBNMjVfY29yciwgZ3JvdXAgPSBzZW5zb3IsIGNvbG91ciA9IHNlbnNvciwgDQogICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlMCgiQm94OiAiLCBzaXRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5FeHA6ICIsIGV4cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+U291cmNlOiAiLCBzb3VyY2UpKSkgKw0KICBsYWJzKHkgPSAiUE0yLjUgKHVnL20zKSIpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSBmaWx0ZXIoZHQsIGV4cCAhPSAiIiksIGFlcyh4ID0gZGF0ZSx5ID0gcG0yLjUpLCBjb2xvdXIgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikrDQogIHNjYWxlX3hfZGF0ZXRpbWUoKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCJTRFMwMTgiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKStmYWNldF93cmFwKH5leHAsIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikNCg0KcF9zcHMwMzAgPC0gZ2dwbG90KCkrDQogIGdlb21fbGluZShkYXRhID0gZmlsdGVyKGRmX2NhbGlicmF0ZWQsIHNlbnNvcl8xPT0iU1BTMDMwIiwgZXhwICE9ICIiKSwNCiAgICAgICAgICAgIGFlcyh4ID0gZGF0ZSwgeSA9IFBNMjVfY29yciwgZ3JvdXAgPSBzZW5zb3IsIGNvbG91ciA9IHNlbnNvciwgDQogICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlMCgiQm94OiAiLCBzaXRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5FeHA6ICIsIGV4cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+U291cmNlOiAiLCBzb3VyY2UpKSkgKw0KICBsYWJzKHkgPSAiUE0yLjUgKHVnL20zKSIpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSBmaWx0ZXIoZHQsIGV4cCAhPSAiIiksIGFlcyh4ID0gZGF0ZSx5ID0gcG0yLjUpLCBjb2xvdXIgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikrDQogIHNjYWxlX3hfZGF0ZXRpbWUoKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCJTUFMwMzAiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKStmYWNldF93cmFwKH5leHAsIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikNCg0KcF9ocG1hIDwtIGdncGxvdCgpKw0KICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihkZl9jYWxpYnJhdGVkLCBzZW5zb3JfMT09IkhQTUExMTVTMCIsIGV4cCAhPSAiIiksDQogICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSBQTTI1X2NvcnIsIGdyb3VwID0gc2Vuc29yLCBjb2xvdXIgPSBzZW5zb3IsIA0KICAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZTAoIkJveDogIiwgc2l0ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+RXhwOiAiLCBleHAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPlNvdXJjZTogIiwgc291cmNlKSkpICsNCiAgbGFicyh5ID0gIlBNMi41ICh1Zy9tMykiKSArDQogIGdlb21fbGluZShkYXRhID0gZmlsdGVyKGR0LCBleHAgIT0gIiIpLCBhZXMoeCA9IGRhdGUseSA9IHBtMi41KSwgY29sb3VyID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpKw0KICBzY2FsZV94X2RhdGV0aW1lKCkgKyB0aGVtZV9idygpICsgZ2d0aXRsZSgiSFBNQTExNVMwIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkrZmFjZXRfd3JhcCh+ZXhwLCBuY29sID0gMSwgc2NhbGVzID0gImZyZWVfeCIpDQoNCmdncGxvdGx5KHBfb3BjcjEsIGR5bmFtaWNUaWNrcyA9IFRSVUUpDQpnZ3Bsb3RseShwX3BtczUwMDMsIGR5bmFtaWNUaWNrcyA9IFRSVUUpDQpnZ3Bsb3RseShwX3NkczAxOCwgZHluYW1pY1RpY2tzID0gVFJVRSkNCmdncGxvdGx5KHBfc3BzMDMwLCBkeW5hbWljVGlja3MgPSBUUlVFKQ0KZ2dwbG90bHkocF9ocG1hLCBkeW5hbWljVGlja3MgPSBUUlVFKQ0KYGBgDQoNCk5vdyBpZiB3ZSBleHRyYWN0IHRoZSBwZWFrcw0KDQpgYGB7cn0NCnBlYWtzPC1yZWFkUkRTKGZpbGU9ImRhdGFzZXRzL3BlYWtzX2NoYXJhY3RlcmlzdGljcy5yZHMiKSANCg0KDQpyZXMgPC0gZGZfY2FsaWJyYXRlZCAlPiUNCiAgICBmaWx0ZXIoZGF0ZT49YXMuUE9TSVhjdChwYXN0ZSgiMjAxOS0wOS0wNSIsIHBlYWtzWzEsXSRTdGFydCksdHo9IlVUQyIpLCBkYXRlPD1hcy5QT1NJWGN0KHBhc3RlKCIyMDE5LTA5LTA1IiwgcGVha3NbMSxdJEVuZCksdHo9IlVUQyIpKSAlPiUNCiAgICBncm91cF9ieShzZW5zb3IpICU+JQ0KICBmaWx0ZXIoUE0yNT49MSkgJT4lDQogIHN1bW1hcmlzZShtYXhfdmFsdWUgPSBtYXgoUE0yNV9jb3JyKSkgJT4lDQogICAgbXV0YXRlKEV4cGVyaW1lbnQgPSBwZWFrc1sxLF0kRXhwZXJpbWVudCwgU291cmNlID0gcGVha3NbMSxdJFNvdXJjZSwgVmFyaWF0aW9uPSBwZWFrc1sxLF0kVmFyaWF0aW9uLCBOdW1iZXIgPSBwZWFrc1sxLF0kTnVtYmVyKQ0KZm9yKHJvdyBpbiAyOm5yb3cocGVha3MpKXsNCiAgZGZfY2FsaWJyYXRlZCAlPiUNCiAgICBmaWx0ZXIoZGF0ZT49YXMuUE9TSVhjdChwYXN0ZSgiMjAxOS0wOS0wNSIsIHBlYWtzW3JvdyxdJFN0YXJ0KSx0ej0iVVRDIiksIGRhdGU8PWFzLlBPU0lYY3QocGFzdGUoIjIwMTktMDktMDUiLCBwZWFrc1tyb3csXSRFbmQpLHR6PSJVVEMiKSkgJT4lDQogICAgZ3JvdXBfYnkoc2Vuc29yKSAlPiUNCiAgICAgIGZpbHRlcihQTTI1Pj0xKSAlPiUNCiAgc3VtbWFyaXNlKG1heF92YWx1ZSA9IG1heChQTTI1X2NvcnIpKSAlPiUNCiAgICBtdXRhdGUoRXhwZXJpbWVudCA9IHBlYWtzW3JvdyxdJEV4cGVyaW1lbnQsIFNvdXJjZSA9IHBlYWtzW3JvdyxdJFNvdXJjZSwgVmFyaWF0aW9uPSBwZWFrc1tyb3csXSRWYXJpYXRpb24sIE51bWJlciA9IHBlYWtzW3JvdyxdJE51bWJlcikgLT4gdG1wDQogIHJlczwtcmJpbmQocmVzLHRtcCkNCiAgDQp9IA0KcmVzICU+JQ0KICBpbm5lcl9qb2luKHBlYWtzLCBieT1jKCJTb3VyY2UiLCAiRXhwZXJpbWVudCIsICJWYXJpYXRpb24iLCAiTnVtYmVyIikpIC0+cmVzX2JpbmQNCg0KcmVzX2JpbmQ8LXJlc19iaW5kICU+JQ0KICBtdXRhdGUocmF0aW8gPSBtYXhfdmFsdWUvQ29uY2VudHJhdGlvbikNCg0KDQoNCmRmMjwtY1NwbGl0KGluZHQ9cmVzX2JpbmQsc3BsaXRDb2xzID0gYygic2Vuc29yIiksc2VwPSItIixkaXJlY3Rpb249IndpZGUiLGRyb3A9RkFMU0UpDQoNCmRmMiAlPiUNCiAgc2VsZWN0KC1zZW5zb3JfMiwtc2Vuc29yXzMpLT5yZXNfYmluDQoNCg0KYGBgDQoNCiMgSW5mbHVlbmNlIG9mIHRoZSBjb25jZW50cmF0aW9uIG9uIHRoZSB2YWx1ZSBvZiB0aGUgcmF0aW8NCg0KYGBge3J9DQoNCnJlc19iaW4gJT4lDQogIGZpbHRlcihWYXJpYXRpb24gPT0gIlBlYWsiKSAlPiUNCiAgZ2dwbG90KGFlcyh4PUV4cGVyaW1lbnQseT1yYXRpbykpICsgDQogIGdlb21fdmlvbGluKGRyYXdfcXVhbnRpbGVzID0gYygwLjI1LCAwLjUsIDAuNzUpKSsNCiAgZmFjZXRfd3JhcChzZW5zb3JfMX5Tb3VyY2UsbmNvbD00KSt5bGFiKCJSYXRpbyBzZW5zb3IvZHVzdHRyYWsiKSt0aGVtZV9idygpLT5wDQpwDQoNCnJlc19iaW4gJT4lDQogIGZpbHRlcihWYXJpYXRpb24gPT0gIlBlYWsiKSAlPiUNCiAgZ2dwbG90KGFlcyh4PUV4cGVyaW1lbnQseT1yYXRpbykpICsgDQogIGdlb21fYm94cGxvdCgpKw0KICBmYWNldF93cmFwKHNlbnNvcl8xflNvdXJjZSxuY29sPTIpK3lsYWIoIlJhdGlvIHNlbnNvci9kdXN0dHJhayIpK3RoZW1lX2J3KCktPnANCnANCiNnZ3NhdmUocCxmaWxlbmFtZSA9ICJwZWFrc19yYXRpby5wbmciLHdpZHRoID0gMTIsIGhlaWdodCA9IDEyKQ0KDQoNCnJlc19iaW4gJT4lDQogIGZpbHRlcihWYXJpYXRpb24gPT0gIlBlYWsiKSAlPiUNCiAgZ2dwbG90KGFlcyh4PUV4cGVyaW1lbnQseT1yYXRpbykpICsgDQogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpKw0KICBmYWNldF93cmFwKHNlbnNvcl8xflNvdXJjZSxuY29sPTIpK3lsYWIoIlJhdGlvIHNlbnNvci9kdXN0dHJhayIpK3RoZW1lX2J3KCkrDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAscXVhbnRpbGUocmVzX2JpbiRyYXRpbywgYygwLjkpKSkpIC0+IHANCnANCiNnZ3NhdmUocCxmaWxlbmFtZSA9ICJwZWFrc19yYXRpb19ub19vdXRsaWVycy5wbmciLHdpZHRoID0gMTIsIGhlaWdodCA9IDEyKQ0KDQpwPC1yZXNfYmluICU+JQ0KICBmaWx0ZXIoVmFyaWF0aW9uID09ICJQZWFrIikgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgZ2dwbG90KCkgKyBnZW9tX3BvaW50KGFlcyh4PUNvbmNlbnRyYXRpb24seT1yYXRpbyxjb2xvcj1zZW5zb3IpKStmYWNldF93cmFwKHNlbnNvcl8xflNvdXJjZSxuY29sPTQsc2NhbGVzPSJmcmVlIikreWxhYigiUmF0aW8gc2Vuc29yL2R1c3R0cmFrIikNCmdncGxvdGx5KHAsIGR5bmFtaWNUaWNrcyA9IFRSVUUpDQoNCmBgYA0KDQoNCg0KIyBDb21wYXJlIHdpdGggdW5jYWxpYnJhdGVkIGRhdGENCg0KYGBge3J9DQoNCnJlcyA8LSBkZiAlPiUNCiAgICBmaWx0ZXIoZGF0ZT49YXMuUE9TSVhjdChwYXN0ZSgiMjAxOS0wOS0wNSIsIHBlYWtzWzEsXSRTdGFydCksdHo9IlVUQyIpLCBkYXRlPD1hcy5QT1NJWGN0KHBhc3RlKCIyMDE5LTA5LTA1IiwgcGVha3NbMSxdJEVuZCksdHo9IlVUQyIpKSAlPiUNCiAgICBncm91cF9ieShzZW5zb3IpICU+JQ0KICBmaWx0ZXIoUE0yNT49MSkgJT4lDQogIHN1bW1hcmlzZShtYXhfdmFsdWUgPSBtYXgoUE0yNSkpICU+JQ0KICAgIG11dGF0ZShFeHBlcmltZW50ID0gcGVha3NbMSxdJEV4cGVyaW1lbnQsIFNvdXJjZSA9IHBlYWtzWzEsXSRTb3VyY2UsIFZhcmlhdGlvbj0gcGVha3NbMSxdJFZhcmlhdGlvbiwgTnVtYmVyID0gcGVha3NbMSxdJE51bWJlcikNCmZvcihyb3cgaW4gMjpucm93KHBlYWtzKSl7DQogIGRmICU+JQ0KICAgIGZpbHRlcihkYXRlPj1hcy5QT1NJWGN0KHBhc3RlKCIyMDE5LTA5LTA1IiwgcGVha3Nbcm93LF0kU3RhcnQpLHR6PSJVVEMiKSwgZGF0ZTw9YXMuUE9TSVhjdChwYXN0ZSgiMjAxOS0wOS0wNSIsIHBlYWtzW3JvdyxdJEVuZCksdHo9IlVUQyIpKSAlPiUNCiAgICBncm91cF9ieShzZW5zb3IpICU+JQ0KICAgICAgZmlsdGVyKFBNMjU+PTEpICU+JQ0KICBzdW1tYXJpc2UobWF4X3ZhbHVlID0gbWF4KFBNMjUpKSAlPiUNCiAgICBtdXRhdGUoRXhwZXJpbWVudCA9IHBlYWtzW3JvdyxdJEV4cGVyaW1lbnQsIFNvdXJjZSA9IHBlYWtzW3JvdyxdJFNvdXJjZSwgVmFyaWF0aW9uPSBwZWFrc1tyb3csXSRWYXJpYXRpb24sIE51bWJlciA9IHBlYWtzW3JvdyxdJE51bWJlcikgLT4gdG1wDQogIHJlczwtcmJpbmQocmVzLHRtcCkNCiAgDQp9IA0KcmVzICU+JQ0KICBpbm5lcl9qb2luKHBlYWtzLCBieT1jKCJTb3VyY2UiLCAiRXhwZXJpbWVudCIsICJWYXJpYXRpb24iLCAiTnVtYmVyIikpICAlPiUNCiAgbXV0YXRlKHJhdGlvID0gbWF4X3ZhbHVlL0NvbmNlbnRyYXRpb24pLT5yZXNfYmluZF91bmNhbGlicmF0ZWQNCg0KDQpyZXNfYmluZCRzdGF0dXMgPC0gIkNhbGlicmF0ZWQiDQpyZXNfYmluZF91bmNhbGlicmF0ZWQkc3RhdHVzIDwtICJOb3QgQ2FsaWJyYXRlZCINCnJlc19jb21wYXJpc29uIDwtIHJiaW5kKHJlc19iaW5kLCByZXNfYmluZF91bmNhbGlicmF0ZWQpDQoNCmRmMjwtY1NwbGl0KGluZHQ9cmVzX2NvbXBhcmlzb24sc3BsaXRDb2xzID0gYygic2Vuc29yIiksc2VwPSItIixkaXJlY3Rpb249IndpZGUiLGRyb3A9RkFMU0UpDQoNCmRmMiAlPiUNCiAgc2VsZWN0KC1zZW5zb3JfMiwtc2Vuc29yXzMpLT5yZXNfY29tcGFyaXNvbg0KDQoNCg0KYGBgDQoNCmBgYHtyfQ0KDQpyZXNfY29tcGFyaXNvbiRzZW5zb3JfMSA8LSBmYWN0b3IocmVzX2NvbXBhcmlzb24kc2Vuc29yXzEsIGxldmVscyA9IGMoIlBNUzUwMDMiLCAiU1BTMDMwIiwgIkhQTUExMTVTMCIsICJTRFMwMTgiLCAiT1BDUjEiKSkNCg0KcmVzX2NvbXBhcmlzb24kc3RhdHVzIDwtIGZhY3RvcihyZXNfY29tcGFyaXNvbiRzdGF0dXMsIGxldmVscyA9IGMoIk5vdCBDYWxpYnJhdGVkIiwgIkNhbGlicmF0ZWQiKSkNCnJlc19jb21wYXJpc29uICU+JQ0KICBmaWx0ZXIoVmFyaWF0aW9uID09ICJQZWFrIikgJT4lDQogIGdncGxvdChhZXMoeD1FeHBlcmltZW50LHk9cmF0aW8sZmlsbD1zdGF0dXMpKSArIA0KICAgZ2VvbV9ib3hwbG90KHdpZHRoPTAuOCxwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksYWxwaGE9MC44LGx3ZD0wLjMsZmF0dGVuPTAuOCxvdXRsaWVyLnNpemUgPSAwLjgsb3V0bGllci5hbHBoYT0wLjUsb3V0bGllci5zdHJva2U9MCkrDQogIGZhY2V0X3dyYXAoc2Vuc29yXzF+U291cmNlLG5jb2w9NCkreWxhYigiUmF0aW8gc2Vuc29yL2R1c3R0cmFrIikrdGhlbWVfYncoKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1wcmV0dHkoYygtMSw2KSwgbj0xNCksc2VjLmF4aXMgPSBkdXBfYXhpcyhuYW1lPU5VTEwpKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsc2l6ZSA9IDYpKS0+cA0KcF9sZWdlbmQ8LWdldF9sZWdlbmQocCkNCg0KcGxvdF9ncmlkKHBfbGVnZW5kKQ0KDQpwPC1wK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCnArICB0aGVtZShwYW5lbC5zcGFjaW5nID0gdW5pdCgwLCAibGluZXMiKSkgKw0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLDAsMCwwKSwgImxpbmVzIikpDQoNCmdnc2F2ZShwLGZpbGVuYW1lID0gInJhdGlvX2NvbXBhcmlzb25fc3BhY2luZy5zdmciLHVuaXQgPSAibW0iLCB3aWR0aD0gMTgwLCBoZWlnaHQgPSAyNDApDQpnZ3NhdmUoYXNfZ2dwbG90KHBfbGVnZW5kKSxmaWxlbmFtZSA9ICJyYXRpb19jb21wYXJpc29uX2xlZ2VuZC5zdmciLHVuaXQgPSAibW0iLCB3aWR0aD0gMTgwLCBoZWlnaHQgPSAyNDApDQoNCg0KYGBgDQoNCg0KDQoNCg==